﻿package com.sgcc.nfc.lock.presentation.rooms

import android.Manifest
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import com.amap.api.location.AMapLocation
import com.amap.api.location.AMapLocationClient
import com.amap.api.location.AMapLocationClientOption
import com.amap.api.maps.AMap
import com.amap.api.maps.CameraUpdateFactory
import com.amap.api.maps.model.LatLng
import com.amap.api.maps.model.Marker
import com.amap.api.maps.model.MarkerOptions
import com.amap.api.maps.model.MyLocationStyle
import com.google.android.material.snackbar.Snackbar
import com.sgcc.nfc.lock.R
import com.sgcc.nfc.lock.databinding.ActivityLocationPickerBinding

class LocationPickerActivity : AppCompatActivity(), AMap.OnMapClickListener {

    private lateinit var binding: ActivityLocationPickerBinding
    private var map: AMap? = null
    private var marker: Marker? = null
    private var selectedLatLng: LatLng? = null
    private var locationClient: AMapLocationClient? = null
    private var hasAutoCentered = false
    private var userInteracted = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityLocationPickerBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.toolbar.setNavigationOnClickListener { finish() }
        binding.pickerMapView.onCreate(savedInstanceState)
        map = binding.pickerMapView.map
        map?.setOnMapClickListener(this)
        binding.confirmButton.setOnClickListener { confirmSelection() }

        enableLocation()
        setupLocationUi()

        val initialLat = intent.getDoubleExtra(EXTRA_LATITUDE, Double.NaN)
        val initialLng = intent.getDoubleExtra(EXTRA_LONGITUDE, Double.NaN)
        val initialPosition = if (!initialLat.isNaN() && !initialLng.isNaN()) {
            LatLng(initialLat, initialLng)
        } else {
            DEFAULT_LAT_LNG
        }
        updateMarker(initialPosition, animate = false)
        map?.moveCamera(CameraUpdateFactory.newLatLngZoom(initialPosition, DEFAULT_ZOOM))
        startLocationUpdates()
    }

    private fun enableLocation() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), REQUEST_LOCATION)
            return
        }
        map?.isMyLocationEnabled = true
    }

    private fun setupLocationUi() {
        val style = MyLocationStyle()
        style.showMyLocation(true)
        style.interval(2_000L)
        map?.myLocationStyle = style
        map?.uiSettings?.isMyLocationButtonEnabled = true
    }

    private fun startLocationUpdates() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) return
        if (locationClient == null) {
            locationClient = AMapLocationClient(applicationContext).apply {
                setLocationOption(
                    AMapLocationClientOption().apply {
                        isOnceLocationLatest = true
                        isNeedAddress = false
                        locationMode = AMapLocationClientOption.AMapLocationMode.Hight_Accuracy
                    }
                )
                setLocationListener { location -> handleLocationResult(location) }
            }
        }
        locationClient?.startLocation()
    }

    private fun stopLocationUpdates() {
        locationClient?.stopLocation()
    }

    private fun handleLocationResult(location: AMapLocation?) {
        if (location == null || location.errorCode != AMapLocation.LOCATION_SUCCESS) {
            return
        }
        stopLocationUpdates()
        val latLng = LatLng(location.latitude, location.longitude)
        if (!userInteracted || !hasAutoCentered) {
            updateMarker(latLng, animate = true)
            hasAutoCentered = true
        }
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == REQUEST_LOCATION && grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            enableLocation()
            setupLocationUi()
            startLocationUpdates()
        } else {
            Snackbar.make(binding.root, R.string.room_location_permission_rationale, Snackbar.LENGTH_LONG).show()
        }
    }

    private fun confirmSelection() {
        val latLng = selectedLatLng
        if (latLng == null) {
            Snackbar.make(binding.root, R.string.room_validation_location, Snackbar.LENGTH_LONG).show()
            return
        }
        val data = Intent().apply {
            putExtra(EXTRA_LATITUDE, latLng.latitude)
            putExtra(EXTRA_LONGITUDE, latLng.longitude)
        }
        setResult(RESULT_OK, data)
        finish()
    }

    override fun onMapClick(latLng: LatLng) {
        userInteracted = true
        updateMarker(latLng, animate = true)
    }

    private fun updateMarker(latLng: LatLng, animate: Boolean) {
        selectedLatLng = latLng
        if (marker == null) {
            marker = map?.addMarker(MarkerOptions().position(latLng))
        } else {
            marker?.position = latLng
        }
        if (animate) {
            map?.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, DEFAULT_ZOOM))
        }
    }

    override fun onResume() {
        super.onResume()
        binding.pickerMapView.onResume()
    }

    override fun onPause() {
        super.onPause()
        binding.pickerMapView.onPause()
    }

    override fun onDestroy() {
        super.onDestroy()
        binding.pickerMapView.onDestroy()
        stopLocationUpdates()
        locationClient?.onDestroy()
        locationClient = null
    }

    override fun onLowMemory() {
        super.onLowMemory()
        binding.pickerMapView.onLowMemory()
    }

    companion object {
        private const val REQUEST_LOCATION = 201
        private const val DEFAULT_ZOOM = 12f
        private val DEFAULT_LAT_LNG = LatLng(39.9042, 116.4074)

        const val EXTRA_LATITUDE = "extra_latitude"
        const val EXTRA_LONGITUDE = "extra_longitude"

        fun createIntent(context: Context, latitude: Double?, longitude: Double?): Intent =
            Intent(context, LocationPickerActivity::class.java).apply {
                latitude?.let { putExtra(EXTRA_LATITUDE, it) }
                longitude?.let { putExtra(EXTRA_LONGITUDE, it) }
            }
    }
}
